namespace SimpleWebServices.Configuration
{
    using System;
    using System.Collections.ObjectModel;
    using System.Diagnostics.CodeAnalysis;
    using System.Xml;
    using System.Xml.Schema;
    using System.Xml.Serialization;
    using SimpleWebServices.Data;

    [XmlRoot("repositories")]
    public sealed class RepositorySettingCollection : Collection<RepositorySetting>, IXmlSerializable
    {
        public string Default
        {
            get;
            set;
        }

        [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Uri doesn't support XML serialization.")]
        public string Urn
        {
            get;
            set;
        }

        public IRepository this[string key]
        {
            get
            {
                IRepository result = null;

                string value = this.Default;
                foreach (RepositorySetting setting in this)
                {
                    if (string.Equals(key, setting.Key, StringComparison.OrdinalIgnoreCase))
                    {
                        value = setting.Value;
                    }
                }

                if (null == value)
                {
                    result = ServiceLocator.Resolve<IRepository>();
                }
                else
                {
                    result = ServiceLocator.Resolve<IRepository>(value);
                }

                return result;
            }
        }

        public void Add(string key, string id)
        {
            this.Add(new RepositorySetting
            {
                Key = key,
                Value = id
            });
        }

        XmlSchema IXmlSerializable.GetSchema()
        {
            throw new NotSupportedException();
        }

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            if (null == reader)
            {
                throw new ArgumentNullException("reader");
            }

            this.Default = reader.GetAttribute("default");
            this.Urn = reader.GetAttribute("urn");

            if (reader.IsEmptyElement)
            {
                reader.Read();
            }
            else
            {
                string name = reader.Name;
                while (true)
                {
                    if (XmlNodeType.EndElement == reader.NodeType && reader.Name == name)
                    {
                        reader.Read();
                        break;
                    }
                    else if ("repository".Equals(reader.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        this.Add(reader.ReadOuterXml().Deserialize<RepositorySetting>());
                    }
                    else
                    {
                        reader.Read();
                    }
                }
            }
        }

        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            if (null == writer)
            {
                throw new ArgumentNullException("writer");
            }

            if (null != this.Default)
            {
                writer.WriteAttributeString("default", this.Default);
            }

            if (null != this.Urn)
            {
                writer.WriteAttributeString("urn", this.Urn);
            }

            foreach (RepositorySetting setting in this)
            {
                writer.WriteRaw(setting.Serialize().CreateNavigator().OuterXml);
            }
        }
    }
}